home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Dev / gcc263-src.lha / gcc-2.6.3 / cp / g++.c < prev    next >
C/C++ Source or Header  |  1994-10-29  |  13KB  |  544 lines

  1. /* G++ preliminary semantic processing for the compiler driver.
  2.    Copyright (C) 1993, 1994 Free Software Foundation, Inc.
  3.    Contributed by Brendan Kehoe (brendan@cygnus.com).
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /* This program is a wrapper to the main `gcc' driver.  For GNU C++,
  22.    we need to do two special things: a) append `-lg++' in situations
  23.    where it's appropriate, to link in libg++, and b) add `-xc++'..`-xnone'
  24.    around file arguments named `foo.c' or `foo.i'.  So, we do all of
  25.    this semantic processing then just exec gcc with the new argument
  26.    list.
  27.  
  28.    We used to do all of this in a small shell script, but many users
  29.    found the performance of this as a shell script to be unacceptable.
  30.    In situations where your PATH has a lot of NFS-mounted directories,
  31.    using a script that runs sed and other things would be a nasty
  32.    performance hit.  With this program, we never search the PATH at all.  */
  33.  
  34. #include "config.h"
  35. #ifdef __STDC__
  36. #include <stdarg.h>
  37. #else
  38. #include <varargs.h>
  39. #endif
  40. #include <stdio.h>
  41. #include <sys/types.h>
  42. #include <sys/file.h>   /* May get R_OK, etc. on some systems.  */
  43. #include <errno.h>
  44.  
  45. /* Defined to the name of the compiler; if using a cross compiler, the
  46.    Makefile should compile this file with the proper name
  47.    (e.g., "i386-aout-gcc").  */
  48. #ifndef GCC_NAME
  49. #define GCC_NAME "gcc"
  50. #endif
  51.  
  52. /* This bit is set if we saw a `-xfoo' language specification.  */
  53. #define LANGSPEC    (1<<1)
  54. /* This bit is set if they did `-lm' or `-lmath'.  */
  55. #define MATHLIB        (1<<2)
  56.  
  57. /* On MSDOS, write temp files in current dir
  58.    because there's no place else we can expect to use.  */
  59. #ifdef __MSDOS__
  60. #ifndef P_tmpdir
  61. #define P_tmpdir "."
  62. #endif
  63. #ifndef R_OK
  64. #define R_OK 4
  65. #define W_OK 2
  66. #define X_OK 1
  67. #endif
  68. #endif
  69.  
  70. #ifndef VPROTO
  71. #ifdef __STDC__
  72. #define PVPROTO(ARGS)        ARGS
  73. #define VPROTO(ARGS)        ARGS
  74. #define VA_START(va_list,var)    va_start(va_list,var)
  75. #else
  76. #define PVPROTO(ARGS)        ()
  77. #define VPROTO(ARGS)        (va_alist) va_dcl
  78. #define VA_START(va_list,var)    va_start(va_list)
  79. #endif
  80. #endif
  81.  
  82. #ifndef errno
  83. extern int errno;
  84. #endif
  85.  
  86. extern int sys_nerr;
  87. #if defined(bsd4_4) || defined(__NetBSD__)
  88. extern const char *const sys_errlist[];
  89. #else
  90. extern char *sys_errlist[];
  91. #endif
  92.  
  93. /* Name with which this program was invoked.  */
  94. static char *programname;
  95.  
  96. #ifdef HAVE_VPRINTF
  97. /* Output an error message and exit */
  98.  
  99. static void
  100. fatal VPROTO((char *format, ...))
  101. {
  102. #ifndef __STDC__
  103.   char *format;
  104. #endif
  105.   va_list ap;
  106.  
  107.   VA_START (ap, format);
  108.  
  109. #ifndef __STDC__
  110.   format = va_arg (ap, char*);
  111. #endif
  112.  
  113.   fprintf (stderr, "%s: ", programname);
  114.   vfprintf (stderr, format, ap);
  115.   va_end (ap);
  116.   fprintf (stderr, "\n");
  117. #if 0
  118.   /* XXX Not needed for g++ driver.  */
  119.   delete_temp_files ();
  120. #endif
  121.   exit (1);
  122. }
  123.  
  124. static void
  125. error VPROTO((char *format, ...))
  126. {
  127. #ifndef __STDC__
  128.   char *format;
  129. #endif
  130.   va_list ap;
  131.  
  132.   VA_START (ap, format);
  133.  
  134. #ifndef __STDC__
  135.   format = va_arg (ap, char*);
  136. #endif
  137.  
  138.   fprintf (stderr, "%s: ", programname);
  139.   vfprintf (stderr, format, ap);
  140.   va_end (ap);
  141.  
  142.   fprintf (stderr, "\n");
  143. }
  144.  
  145. #else /* not HAVE_VPRINTF */
  146.  
  147. static void
  148. error (msg, arg1, arg2)
  149.      char *msg, *arg1, *arg2;
  150. {
  151.   fprintf (stderr, "%s: ", programname);
  152.   fprintf (stderr, msg, arg1, arg2);
  153.   fprintf (stderr, "\n");
  154. }
  155.  
  156. static void
  157. fatal (msg, arg1, arg2)
  158.      char *msg, *arg1, *arg2;
  159. {
  160.   error (msg, arg1, arg2);
  161. #if 0
  162.   /* XXX Not needed for g++ driver.  */
  163.   delete_temp_files ();
  164. #endif
  165.   exit (1);
  166. }
  167.  
  168. #endif /* not HAVE_VPRINTF */
  169.  
  170. /* More 'friendly' abort that prints the line and file.
  171.    config.h can #define abort fancy_abort if you like that sort of thing.  */
  172.  
  173. void
  174. fancy_abort ()
  175. {
  176.   fatal ("Internal g++ abort.");
  177. }
  178.  
  179. char *
  180. xmalloc (size)
  181.      unsigned size;
  182. {
  183.   register char *value = (char *) malloc (size);
  184.   if (value == 0)
  185.     fatal ("virtual memory exhausted");
  186.   return value;
  187. }
  188.  
  189. /* Return a newly-allocated string whose contents concatenate those
  190.    of s1, s2, s3.  */
  191. static char *
  192. concat (s1, s2, s3)
  193.      char *s1, *s2, *s3;
  194. {
  195.   int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
  196.   char *result = xmalloc (len1 + len2 + len3 + 1);
  197.  
  198.   strcpy (result, s1);
  199.   strcpy (result + len1, s2);
  200.   strcpy (result + len1 + len2, s3);
  201.   *(result + len1 + len2 + len3) = 0;
  202.  
  203.   return result;
  204. }
  205.  
  206. static void
  207. pfatal_with_name (name)
  208.      char *name;
  209. {
  210.   char *s;
  211.  
  212.   if (errno < sys_nerr)
  213.     s = concat ("%s: ", sys_errlist[errno], "");
  214.   else
  215.     s = "cannot open %s";
  216.   fatal (s, name);
  217. }
  218.  
  219. #ifdef __MSDOS__
  220. /* This is the common prefix we use to make temp file names.  */
  221. char *temp_filename;
  222.  
  223. /* Length of the prefix.  */
  224. int temp_filename_length;
  225.  
  226. /* Compute a string to use as the base of all temporary file names.  */
  227. static char *
  228. choose_temp_base_try (try, base)
  229. char *try;
  230. char *base;
  231. {
  232.   char *rv;
  233.   if (base)
  234.     rv = base;
  235.   else if (try == (char *)0)
  236.     rv = 0;
  237.   else if (access (try, R_OK | W_OK) != 0)
  238.     rv = 0;
  239.   else
  240.     rv = try;
  241.   return rv;
  242. }
  243.  
  244. static void
  245. choose_temp_base ()
  246. {
  247.   char *base = 0;
  248.   int len;
  249.  
  250.   base = choose_temp_base_try (getenv ("TMPDIR"), base);
  251.   base = choose_temp_base_try (getenv ("TMP"), base);
  252.   base = choose_temp_base_try (getenv ("TEMP"), base);
  253.  
  254. #ifdef P_tmpdir
  255.   base = choose_temp_base_try (P_tmpdir, base);
  256. #endif
  257.  
  258.   base = choose_temp_base_try ("/usr/tmp", base);
  259.   base = choose_temp_base_try ("/tmp", base);
  260.  
  261.   /* If all else fails, use the current directory! */  
  262.   if (base == (char *)0)
  263.     base = "./";
  264.  
  265.   len = strlen (base);
  266.   temp_filename = xmalloc (len + sizeof("/ccXXXXXX"));
  267.   strcpy (temp_filename, base);
  268.   if (len > 0 && temp_filename[len-1] != '/')
  269.     temp_filename[len++] = '/';
  270.   strcpy (temp_filename + len, "ccXXXXXX");
  271.  
  272.   mktemp (temp_filename);
  273.   temp_filename_length = strlen (temp_filename);
  274.   if (temp_filename_length == 0)
  275.     abort ();
  276. }
  277.  
  278. static void
  279. perror_exec (name)
  280.      char *name;
  281. {
  282.   char *s;
  283.  
  284.   if (errno < sys_nerr)
  285.     s = concat ("installation problem, cannot exec %s: ",
  286.         sys_errlist[errno], "");
  287.   else
  288.     s = "installation problem, cannot exec %s";
  289.   error (s, name);
  290. }
  291.  
  292. /* This is almost exactly what's in gcc.c:pexecute for MSDOS.  */
  293. void
  294. run_dos (program, argv)
  295.      char *program;
  296.      char *argv[];
  297. {
  298.   char *scmd, *rf;
  299.   FILE *argfile;
  300.   int i;
  301.  
  302.   choose_temp_base (); /* not in gcc.c */
  303.  
  304.   scmd = (char *) malloc (strlen (program) + strlen (temp_filename) + 10);
  305.   rf = scmd + strlen (program) + 6;
  306.   sprintf (scmd, "%s.exe @%s.gp", program, temp_filename);
  307.  
  308.   argfile = fopen (rf, "w");
  309.   if (argfile == 0)
  310.     pfatal_with_name (rf);
  311.  
  312.   for (i=1; argv[i]; i++)
  313.     {
  314.       char *cp;
  315.       for (cp = argv[i]; *cp; cp++)
  316.     {
  317.       if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
  318.         fputc ('\\', argfile);
  319.       fputc (*cp, argfile);
  320.     }
  321.       fputc ('\n', argfile);
  322.     }
  323.   fclose (argfile);
  324.  
  325.   i = system (scmd);
  326.  
  327.   remove (rf);
  328.   
  329.   if (i == -1)
  330.     perror_exec (program);
  331. }
  332. #endif /* __MSDOS__ */
  333.  
  334. int
  335. main (argc, argv)
  336.      int argc;
  337.      char **argv;
  338. {
  339.   register int i, j = 0;
  340.   register char *p;
  341.   int verbose = 0;
  342.  
  343.   /* This will be NULL if we encounter a situation where we should not
  344.      link in libg++.  */
  345.   char *library = "-lg++";
  346.  
  347.   /* Used to track options that take arguments, so we don't go wrapping
  348.      those with -xc++/-xnone.  */
  349.   char *quote = NULL;
  350.  
  351.   /* The new argument list will be contained in this.  */
  352.   char **arglist;
  353.  
  354.   /* The name of the compiler we will want to run---by default, it
  355.      will be the definition of `GCC_NAME', e.g., `gcc'.  */
  356.   char *gcc = GCC_NAME;
  357.  
  358.   /* Non-zero if we saw a `-xfoo' language specification on the
  359.      command line.  Used to avoid adding our own -xc++ if the user
  360.      already gave a language for the file.  */
  361.   int saw_speclang = 0;
  362.  
  363.   /* Non-zero if we saw `-lm' or `-lmath' on the command line.  */
  364.   int saw_math = 0;
  365.  
  366.   /* The number of arguments being added to what's in argv.  By
  367.      default it's one new argument (adding `-lg++').  We use this
  368.      to track the number of times we've inserted -xc++/-xnone as well.  */
  369.   int added = 1;
  370.  
  371.   /* An array used to flag each argument that needs a bit set for
  372.      LANGSPEC or MATHLIB.  */
  373.   int *args;
  374.  
  375.   p = argv[0] + strlen (argv[0]);
  376.   while (p != argv[0] && p[-1] != '/')
  377.     --p;
  378.   programname = p;
  379.  
  380.   if (argc == 1)
  381.     fatal ("No input files specified.\n");
  382.  
  383. #ifndef __MSDOS__
  384.   /* We do a little magic to find out where the main gcc executable
  385.      is.  If they ran us as /usr/local/bin/g++, then we will look
  386.      for /usr/local/bin/gcc; similarly, if they just ran us as `g++',
  387.      we'll just look for `gcc'.  */
  388.   if (p != argv[0])
  389.     {
  390.       *--p = '\0';
  391.       gcc = (char *) malloc ((strlen (argv[0]) + 1 + strlen (GCC_NAME) + 1)
  392.                  * sizeof (char));
  393.       sprintf (gcc, "%s/%s", argv[0], GCC_NAME);
  394.     }
  395. #endif
  396.  
  397.   args = (int *) malloc (argc * sizeof (int));
  398.   bzero ((char *) args, argc * sizeof (int));
  399.  
  400.   for (i = 1; i < argc; i++)
  401.     {
  402.       /* If the previous option took an argument, we swallow it here.  */
  403.       if (quote)
  404.     {
  405.       quote = NULL;
  406.       continue;
  407.     }
  408.  
  409.       if (argv[i][0] == '\0' || argv[i][1] == '\0')
  410.     continue;
  411.  
  412.       if (argv[i][0] == '-')
  413.     {
  414.       if (strcmp (argv[i], "-nostdlib") == 0)
  415.         {
  416.           added--;
  417.           library = NULL;
  418.         }
  419.       else if (strcmp (argv[i], "-lm") == 0
  420.            || strcmp (argv[i], "-lmath") == 0)
  421.         args[i] |= MATHLIB;
  422.       else if (strcmp (argv[i], "-v") == 0)
  423.         {
  424.           verbose = 1;
  425.           if (argc == 2)
  426.         {
  427.           /* If they only gave us `-v', don't try to link
  428.              in libg++.  */ 
  429.           added--;
  430.           library = NULL;
  431.         }
  432.         }
  433.       else if (strncmp (argv[i], "-x", 2) == 0)
  434.         saw_speclang = 1;
  435.       else if (((argv[i][2] == '\0'
  436.              && (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
  437.             || strcmp (argv[i], "-Tdata") == 0))
  438.         quote = argv[i];
  439.       else if (library != NULL && ((argv[i][2] == '\0'
  440.              && (char *) strchr ("cSEM", argv[i][1]) != NULL)
  441.             || strcmp (argv[i], "-MM") == 0))
  442.         {
  443.           /* Don't specify libraries if we won't link, since that would
  444.          cause a warning.  */
  445.           added--;
  446.           library = NULL;
  447.         }
  448.       else
  449.         /* Pass other options through.  */
  450.         continue;
  451.     }
  452.       else
  453.     {
  454.       int len; 
  455.  
  456.       if (saw_speclang)
  457.         {
  458.           saw_speclang = 0;
  459.           continue;
  460.         }
  461.  
  462.       /* If the filename ends in .c or .i, put options around it.
  463.          But not if a specified -x option is currently active.  */
  464.       len = strlen (argv[i]);
  465.       if (len > 2
  466.           && (argv[i][len - 1] == 'c' || argv[i][len - 1] == 'i')
  467.           && argv[i][len - 2] == '.')
  468.         {
  469.           args[i] |= LANGSPEC;
  470.           added += 2;
  471.         }
  472.     }
  473.     }
  474.  
  475.   if (quote)
  476.     fatal ("argument to `%s' missing\n", quote);
  477.  
  478.   if (added)
  479.     {
  480.       arglist = (char **) malloc ((argc + added + 1) * sizeof (char *));
  481.  
  482.       for (i = 1, j = 1; i < argc; i++, j++)
  483.     {
  484.       arglist[j] = argv[i];
  485.  
  486.       /* Make sure -lg++ is before the math library, since libg++
  487.          itself uses those math routines.  */
  488.       if (!saw_math && (args[i] & MATHLIB) && library)
  489.         {
  490.           saw_math = 1;
  491.           arglist[j] = library;
  492.           arglist[++j] = argv[i];
  493.         }
  494.  
  495.       /* Wrap foo.c and foo.i files in a language specification to
  496.          force the gcc compiler driver to run cc1plus on them.  */
  497.       if (args[i] & LANGSPEC)
  498.         {
  499.           int len = strlen (argv[i]);
  500.           if (argv[i][len - 1] == 'i')
  501.         arglist[j++] = "-xc++-cpp-output";
  502.           else
  503.         arglist[j++] = "-xc++";
  504.           arglist[j++] = argv[i];
  505.           arglist[j] = "-xnone";
  506.         }
  507.     }
  508.  
  509.       /* Add `-lg++' if we haven't already done so.  */
  510.       if (library && !saw_math)
  511.     arglist[j++] = library;
  512.  
  513.       arglist[j] = NULL;
  514.     }
  515.   else
  516.     /* No need to copy 'em all.  */
  517.     arglist = argv;
  518.  
  519.   arglist[0] = gcc;
  520.  
  521.   if (verbose)
  522.     {
  523.       if (j == 0)
  524.     j = argc;
  525.  
  526.       for (i = 0; i < j; i++)
  527.     fprintf (stderr, " %s", arglist[i]);
  528.       fprintf (stderr, "\n");
  529.     }
  530. #ifndef OS2
  531. #ifdef __MSDOS__
  532.   run_dos (gcc, arglist);
  533. #else /* !__MSDOS__ */
  534.   if (execvp (gcc, arglist) < 0)
  535.     pfatal_with_name (gcc);
  536. #endif /* __MSDOS__ */
  537. #else /* OS2 */
  538.   if (spawnvp (gcc, arglist) < 0)
  539.     pfatal_with_name (gcc);
  540. #endif
  541.  
  542.   return 0;
  543. }
  544.